﻿#include "libunits\units_c.h"

#include <cstring>
#include <iostream>
#include <mutex>
#include <string>

#include "libunits\units.h"

// 错误码映射
const char *units_error_string(UnitsErrorCode code) {
  switch (code) {
    case UNITS_SUCCESS:
      return "Success";
    case UNITS_INVALID_HANDLE:
      return "Invalid handle";
    case UNITS_INVALID_PARAM:
      return "Invalid parameter";
    case UNITS_DIMENSION_NOT_FOUND:
      return "Dimension not found";
    case UNITS_UNIT_NOT_FOUND:
      return "Unit not found";
    case UNITS_CONVERSION_FAILED:
      return "Conversion failed";
    case UNITS_CUSTOM_CONV_EXISTS:
      return "Custom conversion already exists";
    case UNITS_FILE_IO_ERROR:
      return "File I/O error";
    case UNITS_CONFIG_PARSE_ERROR:
      return "Config parse error";
    case UNITS_INVALID_UNIT:
      return "Invalid unit";
    case UNITS_DEFINED_UNITS_PARSE_ERROR:
      return "Defined units parse error";
    case UNITS_UNKNOWN_ERROR:
      return "Unknown error";
    default:
      return "Unrecognized error code";
  }
}

UNITS_API void test_unit_system() { return Units::testUnitSystem(); }

// C++ 包装类
class UnitsWrapper {
 public:
  UnitsWrapper() : unitSystem(Units::UnitSystem::instance()) {
    // 设置默认日志回调
    unitSystem.registerLogger(
        [](const std::string &level, const std::string &msg) {
          std::cerr << "[" << level << "] " << msg << std::endl;
        });
  }

  void setLogger(UnitsLogCallback logger) {
    unitSystem.registerLogger(
        [logger](const std::string &level, const std::string &msg) {
          if (logger) {
            logger(level.c_str(), msg.c_str());
          }
        });
  }

  Units::UnitSystem &unitSystem;
};

// 创建单位系统实例
UNITS_API UnitsErrorCode units_create(UnitsHandle *handle) {
  if (!handle) return UNITS_INVALID_PARAM;
  try {
    *handle = new UnitsWrapper();
    return UNITS_SUCCESS;
  } catch (const std::bad_alloc &) {
    return UNITS_UNKNOWN_ERROR;
  } catch (...) {
    return UNITS_UNKNOWN_ERROR;
  }
}

// 销毁单位系统实例
UNITS_API UnitsErrorCode units_destroy(UnitsHandle handle) {
  if (!handle) return UNITS_INVALID_HANDLE;
  try {
    delete static_cast<UnitsWrapper *>(handle);
    return UNITS_SUCCESS;
  } catch (...) {
    return UNITS_UNKNOWN_ERROR;
  }
}

UNITS_API UnitsErrorCode units_convert_measurement(UnitsHandle handle,
                                                   const char *measurement,
                                                   const char *to,
                                                   double *result) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!measurement || !to || !result) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  double output;
  const auto ret = wrapper->unitSystem.convert(measurement, to, output);
  if (ret == Units::ErrorCode::Success) {
    *result = output;
  }
  return static_cast<UnitsErrorCode>(ret);
}

// 单位转换
UNITS_API UnitsErrorCode units_convert(UnitsHandle handle, double value,
                                       const char *from, const char *to,
                                       double *result) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!from || !to || !result) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.convert(value, from, to, *result);
  return static_cast<UnitsErrorCode>(ret);
}

// 转换为基准单位
UNITS_API UnitsErrorCode units_convert_to_base(UnitsHandle handle, double value,
                                               const char *dimension,
                                               double *result) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!dimension || !result) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.convertToBase(value, dimension, *result);
  return static_cast<UnitsErrorCode>(ret);
}

// 从基准单位转换
UNITS_API UnitsErrorCode units_convert_from_base(UnitsHandle handle,
                                                 double value,
                                                 const char *dimension,
                                                 double *result) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!dimension || !result) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret =
      wrapper->unitSystem.convertFromBase(value, dimension, *result);
  return static_cast<UnitsErrorCode>(ret);
}

// 设置基准单位
UNITS_API UnitsErrorCode units_set_base_unit(UnitsHandle handle,
                                             const char *dimension,
                                             const char *unit) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!dimension || !unit) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.setBaseUnit(dimension, unit);
  return static_cast<UnitsErrorCode>(ret);
}

// 设置当前单位
UNITS_API UnitsErrorCode units_set_current_unit(UnitsHandle handle,
                                                const char *dimension,
                                                const char *unit) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!dimension || !unit) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.setCurrentUnit(dimension, unit);
  return static_cast<UnitsErrorCode>(ret);
}

// 获取基准单位
UNITS_API UnitsErrorCode units_get_base_unit(UnitsHandle handle,
                                             const char *dimension,
                                             char *buffer,
                                             unsigned int buf_size) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!dimension || !buffer || buf_size <= 0) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  std::string result;
  auto ret = wrapper->unitSystem.getBaseUnit(dimension, result);
  if (ret != Units::ErrorCode::Success) {
    return static_cast<UnitsErrorCode>(ret);
  }

  // 安全复制字符串
  size_t len = result.size();
  if (len >= buf_size) {
    len = buf_size - 1;
  }
  if (len > 0) {
    memcpy(buffer, result.c_str(), len);
  }
  buffer[len] = '\0';

  return UNITS_SUCCESS;
}

// 获取当前单位
UNITS_API UnitsErrorCode units_get_current_unit(UnitsHandle handle,
                                                const char *dimension,
                                                char *buffer,
                                                unsigned int buf_size) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!dimension || !buffer || buf_size <= 0) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  std::string result;
  auto ret = wrapper->unitSystem.getCurrentUnit(dimension, result);
  if (ret != Units::ErrorCode::Success) {
    return static_cast<UnitsErrorCode>(ret);
  }

  // 安全复制字符串
  size_t len = result.size();
  if (len >= buf_size) {
    len = buf_size - 1;
  }
  if (len > 0) {
    memcpy(buffer, result.c_str(), len);
  }
  buffer[len] = '\0';

  return UNITS_SUCCESS;
}

// 注册自定义转换
UNITS_API UnitsErrorCode units_register_defined_unit(UnitsHandle handle,
                                                     const char *name,
                                                     const char *definition) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!name || !definition) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret =
      wrapper->unitSystem.registerUserDefinedUnit(name, definition);

  return static_cast<UnitsErrorCode>(ret);
}

UNITS_API UnitsErrorCode units_set_logger(UnitsHandle handle,
                                          UnitsLogCallback logger) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!logger) return UNITS_INVALID_PARAM;  // 提前检查

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  wrapper->setLogger(logger);
  return UNITS_SUCCESS;
}

UNITS_API UnitsErrorCode units_load_config_file(UnitsHandle handle,
                                                const char *file) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!file) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.loadFromConfigFile(file);
  return static_cast<UnitsErrorCode>(ret);
}

UNITS_API UnitsErrorCode units_save_config_file(UnitsHandle handle,
                                                const char *file) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!file) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.saveToConfigFile(file);
  return static_cast<UnitsErrorCode>(ret);
}

UNITS_API UnitsErrorCode units_load_defined_units_from_file(UnitsHandle handle,
                                                            const char *file) {
  if (!handle) return UNITS_INVALID_HANDLE;
  if (!file) return UNITS_INVALID_PARAM;

  auto wrapper = static_cast<UnitsWrapper *>(handle);
  const auto ret = wrapper->unitSystem.loadDefinedUnitsFromFile(file);
  return static_cast<UnitsErrorCode>(ret);
}